package com.erp.framework.util.logger;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.erp.framework.SimpleConstants;

/**
 * The <code>Logger</code> class represents a class designated for logging messages in a better way. <br>
 * 
 * For example, the following are all legal and will work as expected. <code><ul>
 * <li>Logger.fatal(this, "this is an FATAL message"); 
 * <li>Logger.error(this, "this is an ERROR message");
 * <li>Logger.warn(this, "this is a WARN message");
 * <li>Logger.info(this, "this is an INFO message");
 * <li>Logger.debug(this, "this is an DEBUG message");
 * <li>Logger.jsp(<strong>request</strong>, "this is a JSP message");
 * <li>Logger.sql(this, "this is a SQL message");
 * <li>Logger.trace(this, "this is a TRACE message");
 * <li>Logger.field(this, "this is a FIELD message");
 * <li>Logger.all(this, "this is a ALL message");
 * <li>Logger.log(this, "this is a LOG message");
 * <li>Logger.debug(new String(), "this is an DEBUG message");
 * </ul></code> Furthermore, the following are also legal and will perform logging without class object names or jsp file names
 * <code><ul>
 * <li>Logger.fatal("this is an FATAL message"); 
 * <li>Logger.error("this is an ERROR message");
 * <li>Logger.warn("this is a WARN message");
 * <li>Logger.info("this is an INFO message");
 * <li>Logger.debug("this is an DEBUG message");
 * <li>Logger.jsp("this is a JSP message");
 * <li>Logger.sql("this is a SQL message");
 * <li>Logger.trace("this is a TRACE message");
 * <li>Logger.field("this is a FIELD message");
 * <li>Logger.all("this is a ALL message");
 * <li>Logger.log("this is a LOG message");
 * </ul></code>
 * 
 * <br>
 * Log Level Comparison: <br>
 * <code>
 * LOG_LEVEL_DISABLED < LOG_LEVEL_ERROR < LOG_LEVEL_WARN <br>
 * < LOG_LEVEL_INFO < LOG_LEVEL_DEBUG < LOG_LEVEL_JSP <br>
 * < LOG_LEVEL_SQL < LOG_LEVEL_TRACE < LOG_LEVEL_FIELD < LOG_LEVEL_ALL<br>
 * </code><br>
 * <br>
 * 
 * @author 
 * @version 1.0 22/9/2004
 * @since JDK1.0
 */

public final class Logger implements SimpleConstants {

    /**
     * Official java class separator.
     */
    private static final String CLASS_SEPARATOR = ".";

    /**
     * Default system directory separator.
     */
    private static final String DIRECTORY_SEPARATOR = "/";

    /**
     * Default system timestamp format.
     */
    private static final String timestampFormat = "yyyy/MM/dd HH:mm:ss:SSS";

    /**
     * The <code>LOG_LEVEL_DISABLED</code> has the highest possible rank and is intended to turn off logging.
     */
    public static final int LOG_LEVEL_DISABLED = 0;

    /**
     * The <code>LOG_LEVEL_FATAL</code> level designates very severe error events that will presumably lead the application to
     * abort.
     */
    public static final int LOG_LEVEL_FATAL = 1;

    /**
     * The <code>LOG_LEVEL_ERROR</code> level designates error events that might still allow the application to continue
     * running.
     */
    public static final int LOG_LEVEL_ERROR = 2;

    /**
     * The <code>LOG_LEVEL_WARN</code> level designates potentially harmful situations.
     */
    public static final int LOG_LEVEL_WARN = 3;

    /**
     * The <code>LOG_LEVEL_INFO</code> level designates informational messages that highlight the progress of the application at
     * coarse-grained level.
     */
    public static final int LOG_LEVEL_INFO = 5;

    /**
     * The <code>LOG_LEVEL_DEBUG</code> Level designates fine-grained informational events that are most useful to debug an
     * application.
     */
    public static final int LOG_LEVEL_DEBUG = 10;

    /**
     * The <code>LOG_LEVEL_JSP</code> level designates messages that highlight the progress of the JSP pages.
     */
    public static final int LOG_LEVEL_JSP = 15;

    /**
     * The <code>LOG_LEVEL_SQL</code> level designates messages that highlight SQL statements.
     */
    public static final int LOG_LEVEL_SQL = 20;

    /**
     * The <code>LOG_LEVEL_TRACE</code> Level designates very-fine-grained informational events that are most useful to trace an
     * application. Examples include <tt>e.printStackTrace()</tt>.
     */
    public static final int LOG_LEVEL_TRACE = 25;

    /**
     * The <code>LOG_LEVEL_FIELD</code> Level designates extra-fine-grained informational events that are most useful to log
     * variable/field values.
     */
    public static final int LOG_LEVEL_FIELD = 30;

    /**
     * The <code>LOG_LEVEL_ALL</code> has the lowest possible rank and is intended to turn on all logging.
     */
    public static final int LOG_LEVEL_ALL = 50;

    /**
     * The <code>LOG_LEVEL_DISABLED_DESC</code> is the description of the log level, <code>LOG_LEVEL_DISABLED</code>
     */
    public static final String LOG_LEVEL_DISABLED_DESC = "DISABLED";

    /**
     * The <code>LOG_LEVEL_FATAL_DESC</code> is the description of the log level, <code>LOG_LEVEL_FATAL</code>
     */
    public static final String LOG_LEVEL_FATAL_DESC = "FATAL";

    /**
     * The <code>LOG_LEVEL_ERROR_DESC</code> is the description of the log level, <code>LOG_LEVEL_ERROR</code>
     */
    public static final String LOG_LEVEL_ERROR_DESC = "ERROR";

    /**
     * The <code>LOG_LEVEL_WARN_DESC</code> is the description of the log level, <code>LOG_LEVEL_WARN</code>
     */
    public static final String LOG_LEVEL_WARN_DESC = "WARN";

    /**
     * The <code>LOG_LEVEL_INFO_DESC</code> is the description of the log level, <code>LOG_LEVEL_INFO</code>
     */
    public static final String LOG_LEVEL_INFO_DESC = "INFO";

    /**
     * The <code>LOG_LEVEL_DEBUG_DESC</code> is the description of the log level, <code>LOG_LEVEL_DEBUG</code>
     */
    public static final String LOG_LEVEL_DEBUG_DESC = "DEBUG";

    /**
     * The <code>LOG_LEVEL_JSP_DESC</code> is the description of the log level, <code>LOG_LEVEL_JSP</code>
     */
    public static final String LOG_LEVEL_JSP_DESC = "JSP";

    /**
     * The <code>LOG_LEVEL_SQL_DESC</code> is the description of the log level, <code>LOG_LEVEL_SQL</code>
     */
    public static final String LOG_LEVEL_SQL_DESC = "SQL";

    /**
     * The <code>LOG_LEVEL_TRACE_DESC</code> is the description of the log level, <code>LOG_LEVEL_TRACE</code>
     */
    public static final String LOG_LEVEL_TRACE_DESC = "TRACE";

    /**
     * The <code>LOG_LEVEL_FIELD_DESC</code> is the description of the log level, <code>LOG_LEVEL_FIELD</code>
     */
    public static final String LOG_LEVEL_FIELD_DESC = "FIELD";

    /**
     * The <code>LOG_LEVEL_ALL_DESC</code> is the description of the log level, <code>LOG_LEVEL_ALL</code>
     */
    public static final String LOG_LEVEL_ALL_DESC = "ALL";

    /**
     * Default log level variable.
     */
    public static int logLevel = LOG_LEVEL_INFO;

    /**
     * Default log timestamp variable.
     */
    public static boolean logTimestamp = false;

    /**
     * Default log to file variable.
     */
    public static boolean logToFile = false;

    public static String companyCode = "";

    public static void setCompanyCode(String companyCode) {

        Logger.companyCode = companyCode;
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages with timestamp.
     */
    public static boolean isLogTimestamp() {

        return logTimestamp;
    }

    /**
     * Set the system to allow logging messages with timestamp.
     * 
     * @param logTimestamp
     *            true or false.
     */
    public static void setLogTimestamp(boolean logTimestamp) {

        Logger.logTimestamp = logTimestamp;
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages to a local file.
     */
    public static boolean isLogToFile() {

        return logToFile;
    }

    /**
     * Set the system to allow logging messages to a local file.
     * 
     * @param logTimestamp
     *            true or false.
     */
    public static void setLogToFile(boolean logToFile) {

        Logger.logToFile = logToFile;
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is NOT logging messages.
     */
    public static boolean isDisabled() {

        return (LOG_LEVEL_DISABLED == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_FATAL
     */
    public static boolean isFatalLevel() {

        return (LOG_LEVEL_FATAL == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_ERROR
     */
    public static boolean isErrorLevel() {

        return (LOG_LEVEL_ERROR == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_WARN
     */
    public static boolean isWarnLevel() {

        return (LOG_LEVEL_WARN == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_INFO
     */
    public static boolean isInfoLevel() {

        return (LOG_LEVEL_INFO == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_DEBUG
     */
    public static boolean isDebugLevel() {

        return (LOG_LEVEL_DEBUG == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_JSP
     */
    public static boolean isJspLevel() {

        return (LOG_LEVEL_JSP == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_SQL
     */
    public static boolean isSqlLevel() {

        return (LOG_LEVEL_SQL == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_TRACE
     */
    public static boolean isTraceLevel() {

        return (LOG_LEVEL_TRACE == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_FIELD
     */
    public static boolean isFieldLevel() {

        return (LOG_LEVEL_FIELD == logLevel);
    }

    /**
     * Returns a <code>boolean</code> so that it represents if the system is logging messages at the LOG_LEVEL_ALL
     */
    public static boolean isAllLevel() {

        return (LOG_LEVEL_ALL == logLevel);
    }

    /**
     * Returns an <code>int</code> so that it represents the current system is logging level.
     */
    public static int getLogLevel() {

        return logLevel;
    }

    /**
     * Set the system to allow logging messages at the specific <code>int</code> log level.
     * 
     * @param logLevel
     *            Can be one of the following levels: <br>
     *            <ul>
     *            <li>LOG_LEVEL_DISABLED
     *            <li>LOG_LEVEL_FATAL
     *            <li>LOG_LEVEL_ERROR
     *            <li>LOG_LEVEL_WARN
     *            <li>LOG_LEVEL_INFO
     *            <li>LOG_LEVEL_DEBUG
     *            <li>LOG_LEVEL_JSP
     *            <li>LOG_LEVEL_SQL
     *            <li>LOG_LEVEL_TRACE
     *            <li>LOG_LEVEL_FIELD
     *            <li>LOG_LEVEL_ALL
     *            </ul>
     */
    public static void setLogLevel(int logLevel) {

        Logger.logLevel = logLevel;
    }

    /**
     * Returns a <code>String</code> so that it represents the description of the <code>int</code> log level.
     * 
     * @param logLevel
     *            Can be one of the following levels: <br>
     *            <ul>
     *            <li>LOG_LEVEL_DISABLED
     *            <li>LOG_LEVEL_FATAL
     *            <li>LOG_LEVEL_ERROR
     *            <li>LOG_LEVEL_WARN
     *            <li>LOG_LEVEL_INFO
     *            <li>LOG_LEVEL_DEBUG
     *            <li>LOG_LEVEL_JSP
     *            <li>LOG_LEVEL_SQL
     *            <li>LOG_LEVEL_TRACE
     *            <li>LOG_LEVEL_FIELD
     *            <li>LOG_LEVEL_ALL
     *            </ul>
     */
    public static String getLogLevelDesc(int logLevel) {

        switch (logLevel) {
            case LOG_LEVEL_DISABLED:
                return "[" + LOG_LEVEL_DISABLED_DESC + "]";
            case LOG_LEVEL_FATAL:
                return "[" + LOG_LEVEL_FATAL_DESC + "]";
            case LOG_LEVEL_ERROR:
                return "[" + LOG_LEVEL_ERROR_DESC + "]";
            case LOG_LEVEL_WARN:
                return "[" + LOG_LEVEL_WARN_DESC + "]";
            case LOG_LEVEL_INFO:
                return "[" + LOG_LEVEL_INFO_DESC + "]";
            case LOG_LEVEL_DEBUG:
                return "[" + LOG_LEVEL_DEBUG_DESC + "]";
            case LOG_LEVEL_JSP:
                return "[" + LOG_LEVEL_JSP_DESC + "]";
            case LOG_LEVEL_SQL:
                return "[" + LOG_LEVEL_SQL_DESC + "]";
            case LOG_LEVEL_TRACE:
                return "[" + LOG_LEVEL_TRACE_DESC + "]";
            case LOG_LEVEL_FIELD:
                return "[" + LOG_LEVEL_FIELD_DESC + "]";
            case LOG_LEVEL_ALL:
                return "[" + LOG_LEVEL_ALL_DESC + "]";
            default:
                return "";
        }
    }

    /**
     * Returns a <code>String</code> so that it represents the current timestamp of the date.
     */
    public static String getCurrentTimestamp() {

        java.sql.Timestamp timestamp = new java.sql.Timestamp(new java.util.Date().getTime());
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(timestampFormat);
        return sdf.format(timestamp);
    }

    /**
     * Log message at the LOG_LEVEL_FATAL level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void fatal(Object className, Object message) {

        log(LOG_LEVEL_FATAL, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_ERROR level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void error(Object className, Object message) {

        log(LOG_LEVEL_ERROR, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_WARN level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void warn(Object className, Object message) {

        log(LOG_LEVEL_WARN, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_INFO level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void info(Object className, Object message) {

        log(LOG_LEVEL_INFO, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_DEBUG level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void debug(Object className, Object message) {

        log(LOG_LEVEL_DEBUG, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_JSP level.
     * 
     * @param httpRequest
     *            Incoming request information for HTTP servlets. usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void jsp(Object httpRequest, Object message) {

        log(LOG_LEVEL_JSP, httpRequest, message);
    }

    /**
     * Log message at the LOG_LEVEL_SQL level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void sql(Object className, Object message) {

        log(LOG_LEVEL_SQL, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_TRACE level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void trace(Object className, Object message) {

        log(LOG_LEVEL_TRACE, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_FIELD level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void field(Object className, Object message) {

        log(LOG_LEVEL_FIELD, className, message);
    }

    /**
     * Log message at the LOG_LEVEL_ALL level.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void all(Object className, Object message) {

        log(LOG_LEVEL_ALL, className, message);
    }

    /**
     * Log message at the currently-set(default) log level. The message will be printed no matter what.
     * 
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void log(Object className, Object message) {

        log(getLogLevel(), className, message);
    }

    /**
     * Log message at the LOG_LEVEL_FATAL level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void fatal(Object message) {

        fatal(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_ERROR level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void error(Object message) {

        error(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_WARN level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void warn(Object message) {

        warn(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_INFO level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void info(Object message) {

        info(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_DEBUG level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void debug(Object message) {

        debug(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_JSP level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void jsp(Object message) {

        jsp(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_SQL level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void sql(Object message) {

        sql(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_TRACE level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void trace(Object message) {

        trace(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_FIELD level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void field(Object message) {

        field(null, message);
    }

    /**
     * Log message at the LOG_LEVEL_ALL level.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void all(Object message) {

        all(null, message);
    }

    /**
     * Log message at the currently-set(default) log level. The message will be printed no matter what.
     * 
     * @param message
     *            Message to be logged.
     */
    public static void log(Object message) {

        log(getLogLevel(), null, message);
    }

    /**
     * Log message at the <code>int</code> log level.
     * 
     * @param logLevel
     *            Can be one of the following levels: <br>
     *            <ul>
     *            <li>LOG_LEVEL_DISABLED
     *            <li>LOG_LEVEL_FATAL
     *            <li>LOG_LEVEL_ERROR
     *            <li>LOG_LEVEL_WARN
     *            <li>LOG_LEVEL_INFO
     *            <li>LOG_LEVEL_DEBUG
     *            <li>LOG_LEVEL_JSP
     *            <li>LOG_LEVEL_SQL
     *            <li>LOG_LEVEL_TRACE
     *            <li>LOG_LEVEL_FIELD
     *            <li>LOG_LEVEL_ALL
     *            </ul>
     * @param className
     *            Name of the class currently calling this method, usually enter <tt>this</tt>
     * @param message
     *            Message to be logged.
     */
    public static void log(int level, Object className, Object message) {

        try {
            StringBuffer logMessage = new StringBuffer("[" + companyCode + "]: ");
            if ((level != LOG_LEVEL_DISABLED) && (level <= logLevel)) {
                if (isLogTimestamp()) {
                    logMessage.append(getCurrentTimestamp() + ", ");
                }

                logMessage.append(getLogLevelDesc(level));
                logMessage.append(" - ");

                if (LOG_LEVEL_JSP == level) {
                    if ((null != className) && (className instanceof HttpServletRequest)) {
                        logMessage.append(getJspFileName((HttpServletRequest) className));
                        logMessage.append(": ");
                    }
                } else {
                    if (null != className) {
                        logMessage.append(getObjectName(className));
                        logMessage.append(": ");
                    }
                }

                logMessage.append(message);

                if ((level == LOG_LEVEL_ERROR) || (level == LOG_LEVEL_FATAL)) {
                    System.err.println(logMessage.toString());
                } else {
                    System.out.println(logMessage.toString());
                }
            }
        } catch (Exception e) {
            System.err.println("[" + companyCode + "]: " + "Error in Logger: " + e);
            e.printStackTrace();
        }
    }

    /**
     * Returns the <code>String</code> representation of the name of a java <code>Object</code>.
     * 
     * @param obj
     *            Any java object.
     */
    public static String getObjectName(Object obj) {

        String fullName = obj.getClass().getName();
        ArrayList resultList = new ArrayList();
        StringTokenizer st = new StringTokenizer(fullName, CLASS_SEPARATOR);
        while (st.hasMoreTokens()) {
            resultList.add(st.nextToken());
        }
        return ((String) resultList.get(resultList.size() - 1));
    }

    /**
     * Returns the <code>String</code> representation of the name of a java <code>Object</code>, and an
     * <code>ArrayList</code> storing the full java hiearchical class name.
     * 
     * @param obj
     *            Any java object.
     * @param resultList
     *            The resulting array list storing the full java name.
     */
    public static String getObjectName(Object obj, ArrayList resultList) {

        String fullName = obj.getClass().getName();
        StringTokenizer st = new StringTokenizer(fullName, CLASS_SEPARATOR);
        while (st.hasMoreTokens()) {
            resultList.add(st.nextToken());
        }
        return ((String) resultList.get(resultList.size() - 1));
    }

    /**
     * Returns the <code>String</code> representation of the name of a java <code>Object</code>, and a <code>String</code>
     * of the full java hiearchical class name.
     * 
     * @param obj
     *            Any java object.
     */
    public static String getObjectFullName(Object obj) {

        return obj.getClass().getName();
    }

    /**
     * Returns the <code>String</code> representation of the name of a java jsp file name.
     * 
     * @param request
     *            Incoming request information for HTTP servlets.
     */
    public static String getJspFileName(HttpServletRequest request) {

        String servletPath = request.getServletPath();
        ArrayList resultList = new ArrayList();
        StringTokenizer st = new StringTokenizer(servletPath, DIRECTORY_SEPARATOR);
        while (st.hasMoreTokens()) {
            resultList.add(st.nextToken());
        }
        return ((String) resultList.get(resultList.size() - 1));
    }

    /**
     * Returns the <code>String</code> representation of the full java servlet context name.
     * 
     * @param request
     *            Incoming request information for HTTP servlets.
     */
    public static String getServerContext(HttpServletRequest request) {

        String serverStr = "";
        try {
            String serverName = request.getServerName();
            InetAddress addr = serverName.equalsIgnoreCase("localhost") ? InetAddress.getLocalHost() : InetAddress
                    .getByName(serverName);
            serverStr = request.getScheme() + "://" + addr.getHostAddress() + ":" + request.getServerPort()
                    + request.getContextPath();
        } catch (Exception e) {
            System.err.println("[" + companyCode + "]: " + "Error in  Logger.getServerContext(): " + e);
        }
        return serverStr;
    }

    /**
     * Set the system logging level from the <code>System</code> stored property.
     */
    public static void setLogLevelFromSystem() {

        String logLevel = System.getProperty("LOG_LEVEL");

        if ((logLevel != null) && (!logLevel.equals(""))) {
            Logger.setLogLevel(Integer.parseInt(logLevel));
        }

        String companyCode = System.getProperty("COMPANY_CODE");
        Logger.setCompanyCode(companyCode);
    }

    /**
     * Set the system to allow logging with timestamp from the <code>System</code> stored property.
     */
    public static void setLogTimestampFromSystem() {

        String logTimestamp = System.getProperty("LOG_TIMESTAMP");

        if ((logTimestamp != null) && (!logTimestamp.equals(""))) {
            Logger.setLogTimestamp(logTimestamp.equals(GENERIC_YES) ? true : false);
        }
    }

    /**
     * Set the system to allow logging to a local file from the <code>System</code> stored property.
     */
    public static void setLogToFileFromSystem() {

        String logToFile = System.getProperty("LOG_TO_FILE");

        if ((logToFile != null) && (!logToFile.equals(""))) {
            Logger.setLogToFile(logToFile.equals(GENERIC_YES) ? true : false);
        }
    }

    public static void logExceptions(Object className, Exception e) {

        if (JAVA_VERSION_NO.compareTo(System.getProperty(JAVA_VERSION_SYS_NAME)) <= 0) {
            // ExceptionStackTrace.printStackTraceInfo(e);
            error(className, e.getMessage());
            if (isTraceLevel()) {
                e.printStackTrace();
            }
        } else {
            error(className, e.getMessage());
            if (isTraceLevel()) {
                e.printStackTrace();
            }
        }
    }

    public static void logExceptions(Exception e) {

        if (JAVA_VERSION_NO.compareTo(System.getProperty(JAVA_VERSION_SYS_NAME)) <= 0) {
            // ExceptionStackTrace.printStackTraceInfo(e);
            error(e.getMessage());
            if (isTraceLevel()) {
                e.printStackTrace();
            }
        } else {
            error(e.getMessage());
            if (isTraceLevel()) {
                e.printStackTrace();
            }
        }
    }

    // must use StringBuffer, otherwise will have higher calling priority than
    // logExeptions(Exception e, Object params);
    public static void logExceptions(Exception e, StringBuffer filename) {

        try {
            String randomTimestamp = String.valueOf(new java.util.Date().getTime()) + "-" + String.valueOf(Math.random());
            FileOutputStream fos = new FileOutputStream(filename.toString() + "_" + randomTimestamp + ".log");
            PrintStream ps = new PrintStream(fos);
            if (isTraceLevel()) {
                e.printStackTrace();
                e.printStackTrace(ps);
            }
            ps.close();
            fos.close();
        } catch (FileNotFoundException fe) {
            error(fe.getMessage());
            if (isTraceLevel()) {
                fe.printStackTrace();
            }
        } catch (IOException ioe) {
            error(ioe.getMessage());
            if (isTraceLevel()) {
                ioe.printStackTrace();
            }
        }
    }

    public static void logExceptions(Exception e, HttpServletResponse response) {

        try {
            if (!response.isCommitted()) {
                response.setContentType("text/plain");
                PrintWriter pw = response.getWriter();
                if (isTraceLevel()) {
                    e.printStackTrace();
                    e.printStackTrace(pw);
                }
                pw.close();
            }
        } catch (IOException ioe) {
            error(ioe.getMessage());
            if (isTraceLevel()) {
                ioe.printStackTrace();
            }
        }
    }

}